package oop.ex3.filemanager.actions;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;

import oop.ex3.messages.FileMessage;
import oop.ex3.messages.MessageInterface;
import oop.ex3.messages.SimpleMessage;
import oop.ex3.messages.ValidHeaders;
import oop.ex3.messages.exception.InvalidHeaderException;
import oop.ex3.messages.exception.UnexpectedMessageEndException;


import oop.ex3.filemanager.FMContext;
import oop.ex3.filemanager.FileInfo;
import oop.ex3.filemanager.actions.exceptions.InvalidNumOfParamsException;
import oop.ex3.filemanager.actions.exceptions.RecievedError;
import oop.ex3.nameserver.exception.UnexpectedMessageException;
import oop.ex3.sockets.ClientSocket;

public class RenameFile extends FmAction{

	private static final int NUM_OF_PARAMS = 3;
	private static final int OLDNAME_PLACE = 1;
	private static final int NEWNAME_PLACE = 2;

	/**
	 * constructor for action
	 * @param context
	 */
	public RenameFile(FMContext context) {
		super(context);
	}

	/**
	 * rename a file in FM's DB
	 * @param params- commands params array
	 * @throws InvalidNumOfParamsException 
	 * @throws InterruptedException 
	 * @throws IOException 
	 * @throws UnknownHostException 
	 */
	public void run(String[] params) 
	throws InvalidNumOfParamsException, InterruptedException, UnknownHostException, IOException {
		if (params.length != NUM_OF_PARAMS){
				throw new InvalidNumOfParamsException();
		}
		String file = params[OLDNAME_PLACE];
		if (!_context.containsFile(file)){
			System.out.println("It is impossible to rename an absent file");
		}
		else if (_context.containsFile(params[NEWNAME_PLACE])){
			System.out.println("It is illegal to use an existing" +
					" file name as a new name");
		}
		else {
			FileInfo fileInfo = _context.removeFile(file);
//				Object lock = fileInfo.getLock();
			while (fileInfo._numOfUploads.intValue() != 0){
				System.out.println("uploads" +fileInfo._numOfUploads);
				synchronized(fileInfo){
					try {
						fileInfo.wait(5000);	
					} catch (Exception e){
						System.out.println("aaaaaaaaaaaaaaaaaaaaa");
					}
			
				}	
			}
			//create new name file
			File destFile = new File(_context.getDir()+
					File.separator+params[NEWNAME_PLACE]);
			if (fileInfo.renameFile(destFile)){
				//add new file to filesDB
				_context.addFile(params[NEWNAME_PLACE], fileInfo);
				
				//TODO not sure it's ok to update all servers at once
				//update all servers
				for (InetSocketAddress server: _context.getServersSet()){
					ClientSocket s = new ClientSocket(server);
					try {
						performHandShake(s);
						FileMessage msg = new 
						FileMessage(ValidHeaders.DONTCONTAINFILE, 
							params[OLDNAME_PLACE]);
						s.SendMessage(msg);
						waitForDone(s);
						finishSession(s);
						s.closeClientSocket();
					} catch (UnexpectedMessageEndException e1) {
						finishSession(s);
						s.closeClientSocket();
					} catch (UnexpectedMessageException e1) {
						finishSession(s);
						s.closeClientSocket();
					} catch (RecievedError e1) {
						finishSession(s);
					s.closeClientSocket();
					} catch (InvalidHeaderException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					s = new ClientSocket(server);
					try {
						performHandShake(s);
						FileMessage msg = new 
						FileMessage(ValidHeaders.CONTAINFILE, 
								params[NEWNAME_PLACE]);
						s.SendMessage(msg);
						waitForDone(s);
						finishSession(s);
						s.closeClientSocket();
					} catch (UnexpectedMessageEndException e1) {
						finishSession(s);
						s.closeClientSocket();
					} catch (UnexpectedMessageException e1) {
						finishSession(s);
						s.closeClientSocket();
					} catch (RecievedError e1) {
						finishSession(s);
						s.closeClientSocket();
					} catch (InvalidHeaderException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
				//notify user
				System.out.println("Renaming Done");
			}
		}
	}

}
